#include "break_up.h"
#include "../../layout/layout.hpp"
#include "../../select/select_cmd.hpp"
#include "../../undoRedo/undoRedo.hpp"
#include "../../utils/kutils.h"

namespace qbe::BreakUp {
void exit(ecs::Query query, state::AllModeType enter_mode) {}
void init(entt::registry& reg, ecs::Commands commands, ecs::Query query) {}
void update(entt::registry& ecs_reg, ecs::Query query, ecs::Bus& bus, ecs::EventWriter<msg::RenderEvent> event) {
  auto& state = query.get_resource<state::State>();

  // 仅在模式执行
  if (state.getEditingMode() != state::EditingModeType::BreakUp)
    return;
  //获取当前操作的Cell
  auto& cmd = query.get_resource<layout::CellCmd>();
  auto cell = cmd.get_cell();
  auto& reg = cell->reg;
  auto& cell_state = query.get_resource<layout::CellState>();
  //获取undo/red0
  auto& unredoMoudel = query.get_resource<undoRedoT::UndoRedoModule>();

  //获取选择对象
  std::vector<entt::entity> select_arr;
  for (auto [e] : reg.view<select::SelectTag>().each()) {
    select_arr.push_back(e);
  }
  if (select_arr.empty()) {
    state.switchMode(state::EditingModeType::None);
    return;
  }

  auto& param = query.get_resource<BreakUpModel>();
  if (param.is_open_ui == false) {
    bus.send(UiMessage::BreakUpUi_Open());
    param.is_open_ui = true;
  }

  auto res = bus.receive<UiMessage::BreakUpUi_Ok>();
  if (!res.empty()) {
    std::vector<entt::entity> remove_entitys;
    std::vector<entt::entity> new_entitys;
    for (auto ele : select_arr) {
      //获取实体的组件，不存在返回为nullptr
      auto ptr = reg.try_get<std::shared_ptr<qlib::Reference>>(ele);
      if (ptr == nullptr)
        continue;  //不是Reference不处理
      auto _ref = *ptr;
      //打散一层
      if (res[0].is_break_up_all == false) {
        new_entitys = getAllGraph(query, cell, _ref, res[0].is_reserve, false);
      } else {
        //打散所有的
        new_entitys = getAllGraph(query, cell, _ref, res[0].is_reserve, true);
      }
      if (new_entitys.back() != ele)
        remove_entitys.push_back(ele);
    }

    auto& layout_cmd = query.get_resource<layout::LayoutCmd>();
    unredoMoudel.start(cell);
    for (auto rem : remove_entitys) {
      unredoMoudel.dele(rem);
      layout_cmd.remove(rem);
    }
    for (auto i : new_entitys) {
      if (reg.valid(i) == true) {
        layout_cmd.add(i);
        unredoMoudel.add(i);
      }
    }
    unredoMoudel.end();
    layout_cmd.render_update();  //确定后版图更新
    state.switchMode(state::EditingModeType::None);
    if (param.is_open_ui == true) {
      bus.send(UiMessage::BreakUpUi_Close());
      param.is_open_ui = false;
    }

    auto& select_cmd = query.get_resource<select::SelectCmd>();
    select_cmd.clear_all();
  }

  //界面取消按钮处理
  {
    auto res = bus.receive<UiMessage::BreakUpUi_Cancel>();
    if (!res.empty()) {
      bus.send(UiMessage::BreakUpUi_Close());
      param.is_open_ui = false;
      state.exit();
    }
  }
}
void post(entt::registry& reg, ecs::Commands commands, ecs::Query query, ecs::Bus& bus) {}

std::vector<entt::entity> getAllGraph(ecs::Query query, qlib::Cell::s_ptr current_cell, std::shared_ptr<qlib::Reference> _ref, bool is_reserve_pcell,
                                      bool is_break_up_all) {
  auto& layout_cmd = query.get_resource<layout::LayoutCmd>();
  std::vector<entt::entity> result;
  if (_ref->cell->m_cell_type == qlib::CellType::PCell && is_reserve_pcell == true) {
    for (auto [e, ref] : current_cell->reg.view<qlib::Reference::s_ptr>().each()) {
      if (ref == _ref) {
        result.push_back(e);
        break;
      }
    }
    return result;
  }
  qlib::ReferencePtrArray refs;
  _ref->apply_repetition(refs);
  refs.push_back(_ref);
  for (auto ref : refs) {
    for (auto [e, poly] : ref->cell->reg.view<qlib::Polygon::s_ptr>().each()) {
      auto graph = poly->copy();
      graph->transform(ref->magnification, ref->x_reflection, ref->rotation, ref->origin);
      auto new_entity = layout_cmd.add(graph);
      result.push_back(new_entity);
    }
    for (auto [e, elli] : ref->cell->reg.view<qlib::Ellipse::s_ptr>().each()) {
      auto graph = elli->copy();
      graph->transform(ref->magnification, ref->x_reflection, ref->origin);
      auto new_entity = layout_cmd.add(graph);
      result.push_back(new_entity);
    }
    for (auto [e, rec] : ref->cell->reg.view<qlib::Rectangle::s_ptr>().each()) {
      auto graph = rec->copy();
      graph->transform(ref->magnification, ref->x_reflection, 0, ref->origin);
      auto new_entity = layout_cmd.add(graph);
      result.push_back(new_entity);
    }
    for (auto [e, fan] : ref->cell->reg.view<qlib::Fan::s_ptr>().each()) {
      auto graph = fan->copy();
      graph->transform(ref->magnification, ref->x_reflection, ref->origin);
      auto new_entity = layout_cmd.add(graph);
      result.push_back(new_entity);
    }
    for (auto [e, line] : ref->cell->reg.view<qlib::Path::s_ptr>().each()) {
      auto graph = line->copy();
      graph->transform(ref->magnification, ref->x_reflection, 0, ref->origin);
      auto new_entity = layout_cmd.add(graph);
      result.push_back(new_entity);
    }
    for (auto [e, label] : ref->cell->reg.view<qlib::Label::s_ptr>().each()) {
      auto graph = label->copy();
      graph->transform(ref->magnification, ref->x_reflection, ref->rotation, ref->origin);
      auto new_entity = layout_cmd.add(graph);
      result.push_back(new_entity);
    }
    for (auto [e, text] : ref->cell->reg.view<qlib::Text::s_ptr>().each()) {
      auto graph = text->copy();
      graph->transform(ref->magnification, ref->x_reflection, ref->rotation, ref->origin);
      auto new_entity = layout_cmd.add(graph);
      result.push_back(new_entity);
    }

    for (auto [e, i] : ref->cell->reg.view<qlib::Reference::s_ptr>().each()) {
      if (i->cell->m_cell_type == qlib::CellType::PCell && is_reserve_pcell == true) {
        auto graph = i->copy();
        graph->transform(ref->magnification, ref->x_reflection, ref->rotation, ref->origin);
        // for (auto [e, ref] : current_cell->reg.view<qlib::Reference::s_ptr>().each()) {
        //   if (ref == _ref) {
        //     result.push_back(e);
        //     break;
        //   }
        // }
        auto new_entity = layout_cmd.add(graph);
        result.push_back(new_entity);
        continue;
      }
      auto graph = i->copy();
      graph->transform(ref->magnification, ref->x_reflection, ref->rotation, ref->origin);
      if (is_break_up_all == true) {
        auto ref_graphs = getAllGraph(query, current_cell, graph, is_reserve_pcell, is_break_up_all);
        result.insert(result.end(), ref_graphs.begin(), ref_graphs.end());
      } else {
        auto entity = current_cell->spawn(graph);
        layout_cmd.add<qlib::Reference::s_ptr>(entity);
        layout_cmd.add_cell(graph->cell);
        result.push_back(entity);
      }
    }
  }

  return result;
}

}  // namespace qbe::BreakUp